From 71ea6192741430677147eb6b10da3d94928eb87b Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 11 Sep 2020 21:09:41 -0400 Subject: [PATCH] gtk-demo: Add an emblem demo Add a simple demo for adding emblems to icons using GdkPaintable. --- demos/gtk-demo/demo.gresource.xml | 1 + demos/gtk-demo/meson.build | 1 + demos/gtk-demo/paintable_emblem.c | 186 ++++++++++++++++++++++++++++++ 3 files changed, 188 insertions(+) create mode 100644 demos/gtk-demo/paintable_emblem.c diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml index f179d9819b..551468fd1b 100644 --- a/demos/gtk-demo/demo.gresource.xml +++ b/demos/gtk-demo/demo.gresource.xml @@ -258,6 +258,7 @@ pagesetup.c paintable.c paintable_animated.c + paintable_emblem.c paintable_mediastream.c panes.c password_entry.c diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build index 9ee9777d13..07fd1b2330 100644 --- a/demos/gtk-demo/meson.build +++ b/demos/gtk-demo/meson.build @@ -59,6 +59,7 @@ demos = files([ 'paint.c', 'paintable.c', 'paintable_animated.c', + 'paintable_emblem.c', 'paintable_mediastream.c', 'panes.c', 'password_entry.c', diff --git a/demos/gtk-demo/paintable_emblem.c b/demos/gtk-demo/paintable_emblem.c new file mode 100644 index 0000000000..4c1ecf9b4c --- /dev/null +++ b/demos/gtk-demo/paintable_emblem.c @@ -0,0 +1,186 @@ +/* Paintable/Emblems + * + * This demo shows how GdkPaintable can be used to + * overlay an emblem on top of an icon. The emblem + * can either be another icon, or an arbitrary + * paintable. + */ + +#include + +#include "paintable.h" + +static GtkWidget *window = NULL; + +#define DEMO_TYPE_ICON (demo_icon_get_type ()) +G_DECLARE_FINAL_TYPE (DemoIcon, demo_icon, DEMO, ICON, GObject) + +struct _DemoIcon +{ + GObject parent_instance; + + GdkPaintable *icon; + GdkPaintable *emblem; + GdkPaintableFlags flags; +}; + +struct _DemoIconClass +{ + GObjectClass parent_class; +}; + +void +demo_icon_snapshot (GdkPaintable *paintable, + GtkSnapshot *snapshot, + double width, + double height) +{ + DemoIcon *self = DEMO_ICON (paintable); + + gdk_paintable_snapshot (self->icon, snapshot, width, height); + gtk_snapshot_save (snapshot); + gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0.5 * width, 0)); + gdk_paintable_snapshot (self->emblem, snapshot, 0.5 * width, 0.5 * height); + gtk_snapshot_restore (snapshot); +} + +static GdkPaintableFlags +demo_icon_get_flags (GdkPaintable *paintable) +{ + DemoIcon *self = DEMO_ICON (paintable); + + return self->flags; +} + +static void +demo_icon_paintable_init (GdkPaintableInterface *iface) +{ + iface->snapshot = demo_icon_snapshot; + iface->get_flags = demo_icon_get_flags; +} + +G_DEFINE_TYPE_WITH_CODE (DemoIcon, demo_icon, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, + demo_icon_paintable_init)) + +static void +demo_icon_dispose (GObject *object) +{ + DemoIcon *self = DEMO_ICON (object); + + g_signal_handlers_disconnect_by_func (self->emblem, + gdk_paintable_invalidate_contents, + self); + + g_clear_object (&self->icon); + g_clear_object (&self->emblem); + + G_OBJECT_CLASS (demo_icon_parent_class)->dispose (object); +} + +static void +demo_icon_class_init (DemoIconClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = demo_icon_dispose; +} + +static void +demo_icon_init (DemoIcon *self) +{ + self->flags = GDK_PAINTABLE_STATIC_SIZE | GDK_PAINTABLE_STATIC_CONTENTS; +} + +GdkPaintable * +demo_icon_new_with_paintable (const char *icon_name, + GdkPaintable *emblem) +{ + GtkIconTheme *theme; + GtkIconPaintable *icon; + DemoIcon *self; + + theme = gtk_icon_theme_get_for_display (gdk_display_get_default ()); + + icon = gtk_icon_theme_lookup_icon (theme, + icon_name, NULL, + 128, 1, + GTK_TEXT_DIR_LTR, 0); + + self = g_object_new (DEMO_TYPE_ICON, NULL); + + self->icon = GDK_PAINTABLE (icon); + self->emblem = emblem; + + if ((gdk_paintable_get_flags (emblem) & GDK_PAINTABLE_STATIC_CONTENTS) == 0) + { + self->flags &= ~GDK_PAINTABLE_STATIC_CONTENTS; + + g_signal_connect_swapped (emblem, "invalidate-contents", + G_CALLBACK (gdk_paintable_invalidate_contents), self); + } + + return GDK_PAINTABLE (self); +} + +GdkPaintable * +demo_icon_new (const char *icon_name, + const char *emblem_name) +{ + GtkIconTheme *theme; + GtkIconPaintable *emblem; + + theme = gtk_icon_theme_get_for_display (gdk_display_get_default ()); + + emblem = gtk_icon_theme_lookup_icon (theme, + emblem_name, NULL, + 128, 1, + GTK_TEXT_DIR_LTR, 0); + + return GDK_PAINTABLE (demo_icon_new_with_paintable (icon_name, + GDK_PAINTABLE (emblem))); +} + +GtkWidget * +do_paintable_emblem (GtkWidget *do_widget) +{ + GdkPaintable *icon; + GtkWidget *grid; + GtkWidget *image; + + if (!window) + { + window = gtk_window_new (); + gtk_window_set_display (GTK_WINDOW (window), + gtk_widget_get_display (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "Emblems"); + gtk_window_set_default_size (GTK_WINDOW (window), 300, 200); + g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); + + grid = gtk_grid_new (); + + icon = demo_icon_new ("folder", "starred"); + image = gtk_image_new_from_paintable (icon); + gtk_widget_set_hexpand (image, TRUE); + gtk_widget_set_vexpand (image, TRUE); + gtk_grid_attach (GTK_GRID (grid), image, 0, 0, 1, 1); + + icon = demo_icon_new_with_paintable ("drive-multidisk", + gtk_nuclear_animation_new (FALSE)); + image = gtk_image_new_from_paintable (icon); + gtk_widget_set_hexpand (image, TRUE); + gtk_widget_set_vexpand (image, TRUE); + gtk_grid_attach (GTK_GRID (grid), image, 1, 0, 1, 1); + + gtk_window_set_child (GTK_WINDOW (window), grid); + g_object_unref (icon); + } + + if (!gtk_widget_get_visible (window)) + gtk_widget_show (window); + else + gtk_window_destroy (GTK_WINDOW (window)); + + return window; +} + -- 2.30.2